
#pragma once
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <unordered_map>
#include <sstream>
#include <fstream>

const std::string gspace = " ";
const std::string glinespace = "\r\n";
const std::string glinesep = ": ";
// web根目录
const std::string webroot = "./wwwroot";
// 默认访问的首页
const std::string homepage = "index.html";

// http协议
// 包含请求和应答
// 请求
class Request
{
public:
    Request()
    {
    }
    ~Request()
    {
    }
    // 反序列化接口
    bool Deserilaze(std::string bigstr)
    {
        std::string reqline;
        // 读取第一行，第一行的末尾是"\r\n"
        // 所以在字符串中找到"\r\n"的位置，截取前面部分即可
        auto pos = bigstr.find(glinespace);
        if (pos == std::string::npos)
            return false; // 不包含完整的请求

        // 获取到第一行的内容
        reqline = bigstr.substr(0, pos);
        // 将第一行进行反序列化
        std::stringstream ss(reqline);
        ss >> _method >> _uri >> _version;

        if (_uri == "/") // 表示要访问的资源就是web根目录下的首页
            _uri = webroot + _uri + homepage;
        else
            _uri = webroot + _uri; // 表示要访问特定路径下的资源

        // 删除第一行
        bigstr.erase(0, pos + glinespace.size());
        return true;
    }
    std::string GetUri()
    {
        return _uri;
    }

private:
    std::string _method;  // 请求方法
    std::string _uri;     // uri
    std::string _version; // http版本
    // 请求报头
    std::unordered_map<std::string, std::string> _headers;
    // 空行
    std::string _blankline;
    // 正文
    std::string _text;
};

// 应答
class Response
{
public:
    Response():_blankline(glinespace)
    {
    }
    ~Response()
    {
    }
    // 序列化
    std::string Serilaze()
    {
        // 状态行
        std::string status_line = _version + gspace + std::to_string(_code) + gspace + _desc + glinespace;
        // 响应报头
        std::string resp_header;
        for (auto &header : _headers)
        {
            std::string line = header.first + glinesep + header.second + glinespace;
            resp_header += line;
        }

        return status_line + resp_header + _blankline + _text;
    }
    // 设置想要访问的资源文件
    void SetTargetFile(const std::string file)
    {
        _targetfile = file;
    }
    //将目标文件填写入正文部分
    void SetText()
    {
        std::ifstream in(_targetfile);
        if(!in.is_open())
        {
            return ;
        }
        std::string line;
        while(std::getline(in,line))
        {
            _text+=line;
        }
        in.close();
    }

public:
    std::string _version; // http版本
    int _code;            // 退出码
    std::string _desc;    // 描述退出码的退出信息
    // 应答报头
    std::unordered_map<std::string, std::string> _headers;
    // 空行
    std::string _blankline;
    // 正文
    std::string _text;
    // 文件，用来填充正文
    std::string _targetfile;
};